package com.itcs.app.callback;

import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.itcs.app.properties.BsConfig;
import com.itcs.app.properties.ZsConfig;
import com.itcs.app.service.ItcsTraderecordsService;
import com.itcs.app.service.TransJournalService;
import com.itcs.app.tran.SendBoxSocket;
import com.itcs.app.util.FormDateReportConvertor;
import com.itcs.app.util.MD5Facade;
import com.itcs.app.util.ParamMap;
import com.itcs.app.util.PayChannelCode;
import com.itcs.app.util.PayStatus;
import com.itcs.app.util.PayType;
import com.itcs.app.util.XzzfPay;
import com.itcs.box.domain.BoxResponse;
import com.itcs.box.util.BoxResUtils;
import com.itcs.box.util.LogUtils;
import com.itcs.trading.mapper.TransJournalMapper;
import com.itcs.trading.model.TransJournal;

/**
 * 回调API
 */
@Controller
@RequestMapping("/callBack")
public class CallBackApi {
	private Log logger = LogFactory.getLog(getClass());

	@Autowired
	private TransJournalMapper transJournalMapper;

	@Autowired
	private ItcsTraderecordsService itcsTraderecordsService;

	@Autowired
	private SendBoxSocket sendBoxSocket;

	@Autowired
	private TransJournalService transJournalService;

	@Autowired
	private ZsConfig zsConfig;
	@Autowired
	private BsConfig bsConfig;

	/**
	 * 现在支付,主扫回调 商户后台通知URL
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	@ResponseBody
	@RequestMapping(value = "achBackNotify")
	public void achBackNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
		try {
			// 获取通知数据需要从body中流式读取
			BufferedReader reader = request.getReader();
			StringBuilder reportBuilder = new StringBuilder();
			String tempStr = "";
			while ((tempStr = reader.readLine()) != null) {
				reportBuilder.append(tempStr);
			}
			String reportContent = reportBuilder.toString();
			Map<String, String> dataMap = FormDateReportConvertor.parseFormDataPatternReportWithDecode(reportContent,
					"UTF-8", "UTF-8");

			// dataMap 用于url方式传进来的
			if (dataMap == null || dataMap.size() < 2) {
				dataMap = new HashMap<String, String>();
				ParamMap param = ParamMap.init(request);
				String mhtOrderNo = param.getString("mhtOrderNo");// 自动订单号
				String nowPayOrderNo = param.getString("nowPayOrderNo");// 现在支付流水号
				String payChannelType = param.getString("payChannelType");// 用户所选渠道类型：12 支付宝 13 微信
				String mhtOrderAmt = param.getString("mhtOrderAmt");// 订单交易金额
				String channelOrderNo = param.getString("channelOrderNo");// 渠道订单号,微信或支付宝订单号,支付成功时返回
				String deviceType = param.getString("deviceType");// 0600公众号
				dataMap.put("mhtOrderNo", mhtOrderNo);
				dataMap.put("nowPayOrderNo", nowPayOrderNo);
				dataMap.put("payChannelType", payChannelType);
				dataMap.put("mhtOrderAmt", mhtOrderAmt);
				dataMap.put("channelOrderNo", channelOrderNo);
				dataMap.put("deviceType", deviceType);

			}
			logger.info(LogUtils.build("achBackNotify", "现在支付回调", "订单号:" + dataMap.get("mhtOrderNo"),
					JSON.toJSONString(dataMap)));

			// ================================================现在支付验证-start===========================================
			// 去除签名值
			String signature = dataMap.remove("signature");

			String deviceType = dataMap.get("deviceType");
			if ("05".equals(deviceType)) {
				logger.info(LogUtils.build("achBackNotify", "现在支付被扫回调", "订单号:" + dataMap.get("mhtOrderNo")));

				// 验证签名
				boolean isValidSignature = MD5Facade.validateFormDataParamMD5(dataMap, bsConfig.getAppKey(), signature);
				if (!isValidSignature) {
					response.getOutputStream().write("success=N".getBytes());
					logger.error(LogUtils.build("achBackNotify", "现在支付被扫回调", "签名验证失败", JSON.toJSONString(dataMap)));
					return;
				}
				String mhtOrderNo = dataMap.get("mhtOrderNo");// 自动订单号
				String payChannelType = dataMap.get("payChannelType");
				// 第三方支付代码
				String payChannelCode = PayChannelCode.微信支付;
				// 支付方式
				int payerId = PayType.被扫微信;
				if (PayType.CHANNEL_支付宝.equals(payChannelType)) {
					payChannelCode = PayChannelCode.支付宝支付;
					payerId = PayType.被扫支付宝;
				} else if (PayType.CHANNEL_微信.equals(payChannelType)) {
					payChannelCode = PayChannelCode.微信支付;
				} else {
					// 目前不支付其它类型
				}

				String payResult = "9";

				TransJournal etcsTraderecord = transJournalService.selectByTransNo(mhtOrderNo);
				Integer deviceId = etcsTraderecord.getTerminalNo();// 通讯盒ID
				if (etcsTraderecord == null || etcsTraderecord.getPayState() == PayStatus.支付成功
						|| etcsTraderecord.getPayState() == PayStatus.车道确认支付完成) {
					logger.info(LogUtils.build("achBackNotify", "现在支付被扫回调", "订单已支付或不存在，回调(2008)通讯盒:" + deviceId,
							JSON.toJSONString(dataMap)));
					send2008(deviceId, mhtOrderNo, payResult, payChannelCode);
					return;
				}

				if ("A001".equals(dataMap.get("transStatus"))) {
					payResult = "1";

					etcsTraderecord.setPayerId(payerId);

					String nowPayOrderNo = dataMap.get("nowPayOrderNo");
					if (nowPayOrderNo != null) {
						etcsTraderecord.setdOrderNo(nowPayOrderNo);// 现在支付流水号 聚合订单号
					}
					String channelOrderNo = dataMap.get("channelOrderNo");
					if (channelOrderNo != null) {
						etcsTraderecord.setsOrderNo(channelOrderNo);// 渠道订单号,微信或支付宝订单号,支付成功时返回 第三方订单号
					}

					// 更新支付状态
					etcsTraderecord.setPayState(PayStatus.支付成功);

					transJournalMapper.updateByPrimaryKey(etcsTraderecord);

					logger.info(LogUtils.build("achBackNotify", "现在支付被扫回调", "被扫执行完成，回调(2008)通讯盒:" + deviceId,
							"{mhtOrderNo:" + mhtOrderNo + ",payChannelType:" + payChannelCode + "}"));

					send2008(deviceId, mhtOrderNo, payResult, payChannelCode);

					response.getOutputStream().write("success=Y".getBytes());
				} else {
					logger.info(LogUtils.build("achBackNotify", "现在支付被扫回调", "支付失败，回调(2008)通讯盒:" + deviceId,
							"{mhtOrderNo:" + mhtOrderNo + "}"));

					send2008(deviceId, mhtOrderNo, payResult, payChannelCode);
					return;
				}
			} else {
				logger.info(LogUtils.build("achBackNotify", "现在支付公众号主扫回调", "订单号:" + dataMap.get("mhtOrderNo")));
				// 验证签名
				boolean isValidSignature = MD5Facade.validateFormDataParamMD5(dataMap, zsConfig.getAppKey(), signature);
				if (!isValidSignature) {
					response.getOutputStream().write("success=N".getBytes());
					logger.error(LogUtils.build("achBackNotify", "现在支付公众号主扫回调", "签名验证失败", JSON.toJSONString(dataMap)));
					return;
				}

				String payChannelCode = dataMap.get("payChannelType");
				if (PayType.CHANNEL_支付宝.equals(payChannelCode)) {
					payChannelCode = PayChannelCode.支付宝支付;
				} else if (PayType.CHANNEL_微信.equals(payChannelCode)) {
					payChannelCode = PayChannelCode.微信支付;
				}

				Map<String, String> mapss = itcsTraderecordsService.callBackUpdate(dataMap);
				String state = mapss.get("state");
				String payResult = "1".equals(state) ? "1" : "9";

				String transacSeq = mapss.get("transacSeq");
				String deviceId = mapss.get("deviceId");

				send2008(Integer.parseInt(deviceId), transacSeq, payResult, payChannelCode);

				logger.info(LogUtils.build("achBackNotify", "现在支付被扫", "被扫执行完成，回调(2008)通讯盒:" + deviceId,
						"{transacSeq:" + transacSeq + ",payChannelType:" + payChannelCode + "}"));

				response.getOutputStream().write("success=Y".getBytes());

			}

		} catch (Exception ex) {
			logger.error(LogUtils.build("achBackNotify", "现在支付被扫回调", "回调处理失败," + ex.getMessage()), ex);
			response.getOutputStream().write("success=N".getBytes());
		}
	}

	/**
	 * 发送2008到通讯盒
	 * 
	 * @param deviceId
	 * @param transacSeq
	 * @param payResult
	 * @param payType
	 * @param payChannelCode
	 */
	private void send2008(int deviceId, String transacSeq, String payResult, String payChannelCode) {
		BoxResponse response2008 = BoxResUtils.build2008(String.valueOf(deviceId), transacSeq, payResult,
				PayType.BOX_二维码, payChannelCode, null);
		sendBoxSocket.pubsubRes2BoxServer(response2008);
	}

	/**
	 * 商户前台通知URL
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	@ResponseBody
	@RequestMapping(value = "achFrontNotify")
	public ModelAndView achFrontNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
		try {
			// 获取通知数据需要从body中流式读取
			BufferedReader reader = request.getReader();
			StringBuilder reportBuilder = new StringBuilder();
			String tempStr = "";
			while ((tempStr = reader.readLine()) != null) {
				reportBuilder.append(tempStr);
			}
			String reportContent = reportBuilder.toString();
			Map<String, String> dataMap = FormDateReportConvertor.parseFormDataPatternReportWithDecode(reportContent,
					"UTF-8", "UTF-8");
			if (dataMap == null || dataMap.size() < 2) {
				dataMap = new HashMap<String, String>();
				ParamMap param = ParamMap.init(request);
				String mhtOrderNo = param.getString("mhtOrderNo");// 自动订单号
				String nowPayOrderNo = param.getString("nowPayOrderNo");// 现在支付订单号
				String payChannelType = param.getString("payChannelType");// 用户所选渠道类型：12 支付宝 13 微信
				String mhtOrderAmt = param.getString("mhtOrderAmt");// 订单交易金额
				dataMap.put("mhtOrderNo", mhtOrderNo);
				dataMap.put("nowPayOrderNo", nowPayOrderNo);
				dataMap.put("payChannelType", payChannelType);
				dataMap.put("mhtOrderAmt", mhtOrderAmt);

			}
			logger.info(LogUtils.build("achFrontNotify", "公众号主扫页面回调", "订单号:" + dataMap.get("mhtOrderNo"),
					JSON.toJSONString(dataMap)));

			String userAgent = request.getHeader("user-agent").toLowerCase();
			String channel = PayType.CHANNEL_微信;
			if (userAgent.contains("micromessenger")) {
				channel = PayType.CHANNEL_微信;
				request.setAttribute("payChannelType", "微信");
			} else if (userAgent.contains("alipayclient")) {
				channel = PayType.CHANNEL_支付宝;
				request.setAttribute("payChannelType", "支付宝");
			}

			Map<String, String> gzhcx = XzzfPay.gzhcx(dataMap.get("mhtOrderNo"), channel);

			Boolean isOK = false;
			if (gzhcx == null || "A001".equals(gzhcx.get("transStatus"))) {
				String mhtOrderAmt = gzhcx.get("mhtOrderAmt");
				if (mhtOrderAmt != null && !mhtOrderAmt.trim().equals("")) {
					request.setAttribute("mhtOrderAmt", mhtOrderAmt);
					request.setAttribute("mhtOrderNo", dataMap.get("mhtOrderNo"));
					isOK = true;
					if (PayType.CHANNEL_支付宝.equals(dataMap.get("payChannelType"))) {
						request.setAttribute("payChannelType", "支付宝");
					} else if (PayType.CHANNEL_微信.equals(dataMap.get("payChannelType"))) {
						request.setAttribute("payChannelType", "微信");
					}
					// 2018年2月3日11:07:46 于斌加入返回车牌号，从流水表查询得出实际支付金额和车牌号
					TransJournal transJournal = transJournalService.selectByTransNo(dataMap.get("mhtOrderNo"));
					if (transJournal == null) {// 查不到数据，返回相关信息
						request.setAttribute("carPlate", "未知");
					} else {
						request.setAttribute("carPlate", transJournal.getCarPlate());
						BigDecimal tollFareAmount = transJournal.getTollFare();// 通行费应付金额
						request.setAttribute("mhtOrderAmt",
								tollFareAmount.divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).doubleValue());// 页面单位是元所以除100

					}
				}
			}
			logger.info(LogUtils.build("achFrontNotify", "公众号主扫页面回调",
					"订单号:" + dataMap.get("mhtOrderNo") + ",处理结果:" + isOK));
			if (isOK) {
				return new ModelAndView("/wap4");
			}
		} catch (Exception ex) {
			logger.error(LogUtils.build("achFrontNotify", "公众号主扫页面回调", "回调处理失败," + ex.getMessage()), ex);
		}
		return new ModelAndView("/wap5");
	}
}
